package com.elong.android.specialhouse.utils;

import android.content.Context;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.elong.android.specialhouse.AppConstants;
import com.elong.android.specialhouse.IConfig;
import com.elong.android.specialhouse.interfaces.RequestLocationListener;

import java.io.File;
import java.util.HashMap;

/**
 * 在使用定位信息时，请尽量使用相应的get方法取得需要的位置信息，这样可以方便测试人员使用虚拟位置进行测试，
 * 如果直接调用成员变量，则无法使用虚拟位置 
 */
public class BDLocationManager {

	public static final String TAG = "BDMapManager";

	public static final String CACHE_KEY = "cache_location";

	// 地图定位客户端
	public LocationClient mLocationClient = null;
	// 用户当前位置
	public BDLocation mCurrentLocation = null;
	// 用户当前POI地理位置名称
	public BDLocation mCurrentPOI = null;
	// 是否在国外
	public boolean mIsOverSea = false;
	// 用户所在城市名称
	public String mCityName = null;
	// 用户所在地理位置名称
	public String mAddressName = null;
	// 用户所在国外的地理位置名称
	public String mGlobalAddressName = null;

	//虚拟位置相关
	// 默认北京天安门
	private static double latitude_virtual = 39.914914;
	private static double longitude_virtual = 116.403874;
	private String mCityName_virtual = "北京";
	private String mAddressName_virtual = null;
	private BDLocation mCurrentLocation_virtual = null;
	
	private Context context;

	private RequestLocationListener mLocationListener = null;

	private static BDLocationManager s_instance;

	public static BDLocationManager getInstance() {
		// 如果实例被回收则重建对象并恢复数据
		if (s_instance == null) {
			s_instance = new BDLocationManager();
			s_instance.restoreCacheLocation();
		}
		return s_instance;
	}

	public void init(Context context) {
		mLocationClient = new LocationClient(context);
		this.context = context;

		// 读取缓存的位置信息
		restoreCacheLocation();

		LocationClientOption option = new LocationClientOption();
		option.setLocationMode(LocationMode.Hight_Accuracy);
		// 返回的定位结果是百度经纬度,默认值gcj02
		option.setCoorType("bd09ll");
		// 设置发起定位请求的间隔时间为5000ms
		option.setScanSpan(5000);
		// 返回的定位结果包含地址信息
		option.setIsNeedAddress(true);
		// 返回的定位结果包含手机机头的方向
		option.setNeedDeviceDirect(true);

		option.setProdName("com.elong.android.apartment");

		mLocationClient.setLocOption(option);
		mLocationListener = createLocationListener();
		mLocationClient.registerLocationListener(mLocationListener);
		mLocationClient.start();
		mLocationClient.requestLocation();
	}

	/**
	 * 
	 * @Title: createLocationListener
	 * @Description: 创建定位监听事件
	 * @return RequestLocationListener
	 * @throws
	 */
	private RequestLocationListener createLocationListener() {
		return new RequestLocationListener() {
			@Override
			public void onReceiveLocation(BDLocation location) {
				setLocationInfo(location);
			};
		};
	}

	/**
	 * 
	 * @Title: GetGeoCodeResultListener
	 * @Description: 创建反地理信息搜索接口
	 * @return RequestLocationListener
	 * @throws
	 */
	private OnGetGeoCoderResultListener createGetGeoCodeResultListener() {
		return new OnGetGeoCoderResultListener() {
			
			/** 
		     * onGetReverseGeoCodeResult 搜索（根据坐标-->实地信息） 
		     */
			@Override
			public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
				if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
		            return;  
		        }  
				mCityName_virtual = result.getAddressDetail().city;
				mAddressName_virtual = result.getAddress() ;
				mCurrentLocation_virtual = new BDLocation();
				mCurrentLocation_virtual.setAddrStr(result.getAddress());
				mCurrentLocation_virtual.setLatitude(latitude_virtual);
				mCurrentLocation_virtual.setLongitude(longitude_virtual);
			}
			
			/** 
		     * onGetGeoCodeResult 搜索（根据实地信息-->经纬坐标） 
		     */
			@Override
			public void onGetGeoCodeResult(GeoCodeResult arg0) {}
		};
	}
	
	/**
	 * 
	 * @Title: setLocationInfo
	 * @Description: 设置位置信息
	 * @param location
	 * @return void
	 * @throws
	 */
	private void setLocationInfo(BDLocation location) {
		// 百度地图有时候会返回一个无穷小的数字，此处为了兼容百度的bug,要求经纬度大于1
		if (location != null && location.getLatitude() > 1 && location.getLongitude() > 1) {
			mCurrentLocation = location;
			if (location.getLocType() == BDLocation.TypeGpsLocation) {
				Log.e(TAG, "BDLocation.TypeGpsLocation,getLatitude:" + location.getLatitude() + ",getLongitude:"
						+ location.getLongitude());
			} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
				// 匹配艺龙城市名称
				String result = Utils.retriveCityName(context, location.getCity());
				mCityName= (result == null ? location.getCity() : result);
				mAddressName = location.getAddrStr();
				Log.e(TAG, "BDLocation.TypeNetWorkLocation,getAddrStr:" + location.getAddrStr());
				Log.e(TAG, "getLatitude:" + location.getLatitude() + ",getLongitude:" + location.getLongitude());
			} else {
				Log.e(TAG, "getLatitude:" + location.getLatitude() + ",getLongitude:" + location.getLongitude());
			}

			if (mLocationClient != null && mLocationClient.isStarted() && mLocationListener != null) {
				mLocationClient.unRegisterLocationListener(mLocationListener);
				mLocationClient.stop();
			}

			// 保存定位到的位置信息
			saveLocation2Cache();
		} else {
			mLocationClient.requestLocation();
		}

	}

	/**
	 * 
	 * @Title: requestLocation
	 * @Description: 发起定位请求
	 * @param @param listener
	 * @return void
	 * @throws
	 */
	public void requestLocation(BDLocationListener listener) {
		if (mLocationClient != null) {
			if (!mLocationClient.isStarted()) {
				mLocationClient.start();
			}
			mLocationClient.registerLocationListener(listener);
			mLocationClient.requestLocation();
		}
	}

	/**
	 * 
	 * @Title: requestLocation
	 * @Description: 发起定位请求
	 * @param
	 * @return void
	 * @throws
	 */
	public void requestLocation() {
		if (mLocationClient != null) {
			if (!mLocationClient.isStarted()) {
				mLocationClient.start();
			}

			mLocationClient.requestLocation();
		}
	}

	/**
	 * 
	 * @Title: stopLocationService
	 * @Description: 停止定位服务
	 * @param @param listener
	 * @return void
	 * @throws
	 */
	public void stopLocationService(BDLocationListener listener) {
		if (mLocationClient != null && mLocationClient.isStarted()) {
			mLocationClient.unRegisterLocationListener(listener);
			mLocationClient.stop();
		}
	}

	/**
	 * 
	 * @Title: stopLocationService
	 * @Description: 停止定位服务
	 * @param
	 * @return void
	 * @throws
	 */
	public void stopLocationService() {
		if (mLocationClient != null && mLocationClient.isStarted()) {
			mLocationClient.unRegisterLocationListener(mLocationListener);
			mLocationClient.stop();
		}
	}

	/**
	 * 
	 * @Title: isLocateSuccess
	 * @Description: 是否定位成功(百度地图有时候会返回一个无穷小的数字，此处为了兼容百度的bug,要求经纬度大于1)
	 * @param @return
	 * @return boolean
	 * @throws
	 */
	public boolean isLocateSuccess() {
		return mCurrentLocation != null && mCurrentLocation.getLatitude() > 1 && mCurrentLocation.getLongitude() > 1;
	}

	/**
	 * 
	 * @Title: restoreCacheLocation
	 * @Description: 读取缓存到的地址信息
	 * @param
	 * @return void
	 * @throws
	 */
	private void restoreCacheLocation() {
//		try {
//			String path = Globals.getContext().getCacheDir() + File.separator + CACHE_KEY;
//			HashMap<String, Object> location = null;
//			Object cacheObject = Utils.restoreObject(path);
//			if (cacheObject instanceof HashMap) {
//				location = (HashMap<String, Object>) cacheObject;
//			}
//
//			if (location != null) {
//				mCurrentLocation = new BDLocation();
//				mCurrentLocation.setAddrStr((String) location.get("addrStr"));
//				mCurrentLocation.setLatitude(Utils.convertToDouble(location.get("latitude"), 0.0));
//				mCurrentLocation.setLongitude(Utils.convertToDouble(location.get("longitude"), 0.0));
//				mCityName = (String) location.get("city");
//				mAddressName = (String) location.get("addrStr");
//
//				if (IConfig.DEBUG_ON) {
//					Log.e(TAG,
//							"getLatitude:" + mCurrentLocation.getLatitude() + ",getLongitude:"
//									+ mCurrentLocation.getLongitude());
//					Log.e(TAG, "Restore location successful!AddrStr:" + mAddressName);
//				}
//			}
//		} catch (Exception e) {
//			LogWriter.logException(TAG, "", e);
//		}
	}

	/**
	 * 
	 * @Title: saveLocation2Cache
	 * @Description: 缓存定位到的地址信息
	 * @param
	 * @return void
	 * @throws
	 */
	private void saveLocation2Cache() {
		String path = context.getCacheDir() + File.separator + CACHE_KEY;
		HashMap<String, Object> location = new HashMap<String, Object>();
		location.put("latitude", mCurrentLocation.getLatitude());
		location.put("longitude", mCurrentLocation.getLongitude());
		location.put("addrStr", mCurrentLocation.getAddrStr());
		location.put("city", mCurrentLocation.getCity());

		Utils.saveObject(path, location);

		if (IConfig.DEBUG_ON) {
			Log.e(TAG, "Save location successful!AddrStr:" + mCurrentLocation.getAddrStr());
			Log.e(TAG,
					"getLatitude:" + mCurrentLocation.getLatitude() + ",getLongitude:"
							+ mCurrentLocation.getLongitude());
		}
	}

	/**
	 * 
	 * @Title: getCityName
	 * @Description: 获取百度城市名称
	 * @return String
	 * @throws
	 */
	public String getCityName() {
		String city = mCityName ;
		if(AppConstants.isVirtualLocation){
			city = mCityName_virtual;
		}
		return city;
	}
	
	/**
	 * 
	 * @Title: getElongCityName
	 * @Description: 获取和艺龙城市列表匹配的城市名称
	 * @return String
	 * @throws
	 */
	public String getElongCityName() {
		String city = mCityName ;
		if(AppConstants.isVirtualLocation){
			city = mCityName_virtual;
		}
		String result = Utils.retriveCityName(context, city);
		return result == null ? city : result;
	}

	/**
	 * 
	 * @Title: getAddressName
	 * @Description: 获取地名
	 * @return String
	 * @throws
	 */
	public String getAddressName() {
		if(AppConstants.isVirtualLocation){
			return mAddressName_virtual;
		}
		return BDLocationManager.getInstance().mIsOverSea ? BDLocationManager.getInstance().mGlobalAddressName
				: BDLocationManager.getInstance().mAddressName;
	}

	/**
	 * 
	 * @Title: getLocation
	 * @Description: 获取当前经纬度坐标
	 * @return LatLng
	 * @throws
	 */
	public LatLng getLocation() {
		if(AppConstants.isVirtualLocation){
			return new LatLng(latitude_virtual, longitude_virtual);
		}
		if (mCurrentLocation == null) {
			return null;
		}
		return new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
	}
	
	/**
	 * 
	 * @Title: getCurrentLocation 
	 * @Description: 获取当前位置
	 * @param @return
	 * @return BDLocation
	 * @throws
	 */
	public BDLocation getCurrentLocation(){
		if(AppConstants.isVirtualLocation){
			return mCurrentLocation_virtual;
		}
		return mCurrentLocation;
	}
	
	/**
	 * 
	 * @Title: setVirtualLOcation 
	 * @Description: 设置虚拟坐标经纬度
	 * @param @param lon 经度
	 * @param @param lat 纬度
	 * @return void
	 * @throws
	 */
	public void setVirtualLOcation(double lon , double lat){
		longitude_virtual = lon;
		latitude_virtual = lat ;
		LatLng ll = new LatLng(lat,lon);
		GeoCoder mSearch = GeoCoder.newInstance();
        mSearch.setOnGetGeoCodeResultListener(createGetGeoCodeResultListener());
        mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(ll));
	}
}
